

let BaseGame = require('BaseGame');

cc.Class({
    extends: BaseGame,
    ctor(){
        //游戏得分
        this.score = 0;

        this.arenaData = [
            [0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0],
            // [0, 0, 7, 0],
            // [0, 0, 0, 6, 0],
            // [0, 0, 0, 0, 5, 0],
            // [0, 0, 0, 4, 0, 0, 0],
            // [0, 0, 3, 0, 0, 0],
            // [0, 2, 0, 0, 0],
            // [1, 0, 0, 0],               
        ];
        this.maxLen = 7;
        //单位六边形得宽度
        this.polygonW = 80;
        //单位六边形得高度
        this.polygonH = 90;
        //六边形 x 间距
        this.polygonStepX = 5;
        //六边形 y 间距
        this.polygonStepY = 5;
        //
        this.polygonSpriteFrame = [];
        /*
            a: .
            b: -
            c: \
            d: /
        */
        this.nextPoly = 'b';
        //最大的数字
        this.max = 2;

        this._score = 0;
        this.saveDataTimer = null;
        this.gameOverTimer = null;

        this.dmData = [
            {
                isSelf: false,
                text: '这是一条弹幕'
            },
            {
                isSelf: true,
                text: '这是一条弹幕2222222'
            },            
        ];
    },
    properties: {
        polygonPrefab: cc.Prefab,
        polygon2Prefab: cc.Prefab,
        arenaNode: cc.Node,
        dragPolygonNode: cc.Node,
        dragBoxNode: cc.Node,
        cirNode: cc.Node,
        dmListNode: cc.Node,
        dmControl: cc.Node,
        scoreLabel: {
            type: cc.Label,
            default: null
        },
        score: {
            get: function(){
                return this._score
            },
            set: function(val){
                this._score = val;
                if(this.scoreLabel){
                    this.scoreLabel.string = '得分：'+this._score;
                }
            }
        }
    },
    initCustomConfig(conf){
        //自定义配置
        //console.log(conf)
        //this.clearSaveData();
        this.getCacheData().then((res)=>{
            if(res.code == 200 && res.data.gameData && res.data.gameData.gameData){
                let json = res.data.gameData.gameData;
                for(let name in json){
                    this[name] = json[name];
                }
            }
        });
    },    
    clickStart(){
        //console.log('点击开始游戏！')
    },
    clickRestartBtn(){
        //console.log('点击继续游戏！')
    },
    clickBackList(){
        //console.log('点击返回列表')
        return new Promise((resolve, reject)=>{
            //返回列表前可以做一些事情
            //console.log('Before Back')
            resolve();
        })
    },
    submitCallBack(){
        //console.log('提交分数回调')
        this.clearSaveData();
    },
    hsPlayEnd(){
        console.log('话术播放结束')
        // this.createArena();
        // this.createPolygon(this.nextPoly);
    },    
    startGame(){
        //console.log('游戏开始！')
    },
    resetGame(){
        //console.log('重置游戏！')
        this.resetAll();
    },
    gameOver(){
        //console.log('游戏结束！')
    },
    openGame(){
        //console.log('打开游戏！')
    },
    hideGame(){
        //console.log('隐藏游戏！')
    },
    //保存当前游戏状态
    saveCurStatus(){
        let data = {
            //得到的喜乐豆
            getXLbean: this.getXLbean,
            arenaData: this.getArenaData(),
            startTime: this.startTime,
            score: this.score,
            max: this.max
        }
        let formData = {
            timestamp: Date.now(),
            xileBean: this.getXLbean,
            minusXileBean: 1,
            totalXileBean: 1,
            score: this.score,
            timeuse: this.gameTime,
            gameData: data
        }
        this.cacheData(JSON.stringify(formData));
    },
    //清除保存的状态
    clearSaveData(){
        this.cacheData(JSON.stringify({
            timestamp: Date.now(),
            xileBean: 0,
            totalXileBean: 1,
            minusXileBean: 1,
            score: 0,
            timeuse: 1,
            gameData: {}
        }))
    },
    getArenaData(){
        let arr = [];
        for(let i=0; i<this.arenaData.length; i++){
            let arr2 = [];
            for(let j=0; j<this.arenaData[i].length; j++){
                arr2.push(this.arenaData[i][j].value)
            }
            arr.push(arr2)
        }
        return arr;
    },
    onLoad () { 
        this._onLoad();


        this.getRandNum();
        //开启碰撞检测
        var manager = cc.director.getCollisionManager();
        manager.enabled = true;
        //开启物理系统
        //cc.director.getPhysicsManager().enabled = true;

        this.getCacheData().then((res)=>{
            //console.log('ajax-load')
            if(res.code == 200 && res.data.gameData && res.data.gameData.gameData){
                let json = res.data.gameData.gameData;
                for(let name in json){
                    this[name] = json[name];
                }
            }
            cc.resources.loadDir("imgs", cc.SpriteFrame, (err, assets)=>{
                this.polygonSpriteFrame = assets;
                //console.log(this.polygonSpriteFrame)
                //console.log('img-load')
                this.createArena();
                this.createPolygon(this.nextPoly);
            });            
        }).catch(err=>{
            cc.resources.loadDir("imgs", cc.SpriteFrame, (err, assets)=>{
                this.polygonSpriteFrame = assets;
                //console.log(this.polygonSpriteFrame)
                //console.log('img-load')
                this.createArena();
                this.createPolygon(this.nextPoly);
            });     
        })

        setTimeout(()=>{
            this.dmListNode.emit('initDM', this.dmData)
        }, 0)

        this.dmControl.on('sendDm', (obj)=>{
            this.dmListNode.emit('createOne', obj)
        })


        let downTime = 0;
        this.dragBoxNode.on(cc.Node.EventType.TOUCH_START, ()=>{
            if(this.gameState !== 'start'){
                return false;
            }
            downTime = Date.now();
        })
        this.dragBoxNode.on(cc.Node.EventType.TOUCH_MOVE, (event)=>{
            if(this.gameState !== 'start'){
                return false;
            }
            let curPos = cc.v2(0,0)
            this.dragBoxNode.getPosition(curPos);
            let dis = event.getDelta();
            this.dragBoxNode.setPosition(curPos.add(dis))
        })        
        this.dragBoxNode.on(cc.Node.EventType.TOUCH_END, ()=>{
            if(this.gameState !== 'start'){
                return false;
            }
            if(Date.now()-downTime < 300){
                this.dragBoxNode.setPosition(cc.v2(0,0))
                cc.tween(this.dragBoxNode).by(0.3, {angle: -180}).start()
            }else{
                let child = this.dragPolygonNode.children;
                
                if(child.every(item=>item.capture)){
                    //this.createScoreNode(child[0], -3)
                    child.map(item=>{
                        let pos = item.targetPos;
                        let cloneItem = cc.instantiate(item);
                        cloneItem.setPosition(0,0)
                        this.arenaData[pos[0]][pos[1]].node.addChild( cloneItem )
                        this.arenaData[pos[0]][pos[1]].value = item.value;
                        item.destroy();
                    })
                    if(child.length == 2){
                        if(child[0].value == child[1].value){
                            let pos = child[0].targetPos;
                            this.removePolygon(pos[0], pos[1])
                        }else{
                            let pos1 = child[0].targetPos;
                            this.removePolygon(pos1[0], pos1[1])   
                            let pos2 = child[1].targetPos;
                            this.removePolygon(pos2[0], pos2[1])                                                   
                        }
                    }else{
                        let pos = child[0].targetPos;
                        this.removePolygon(pos[0], pos[1])
                    }

                    this.dragBoxNode.setPosition(cc.v2(0,0))
                    this.createPolygon(this.nextPoly);

                    //this.getXLbean -= 3;
                    //消除
                }else{
                    cc.tween(this.dragBoxNode).to(0.3, {position: cc.v2(0,0)}).call(()=>{
                        child.map(item=>{
                            item.isCancel = false;
                        })
                    }).start()

                    clearTimeout(this.saveDataTimer);
                    this.saveDataTimer = setTimeout(()=>{
                        this.saveCurStatus();
                    }, 5000)
                }

                for(let i=0; i<this.arenaData.length; i++){
                    for(let j=0; j<this.arenaData[i].length; j++){
                        this.arenaData[i][j].node.emit('reset')
                    }
                }

                
                
            }
        }) 

    },
    start () {
        
    },
    //消除
    removePolygon(x, y){
        let res = [];
        let cur = this.arenaData[x][y];
        cur.find = true;
        this.findPolygon(res, cur, x, y);
        if(res.length >= 2){
            this.score+=cur.value*(res.length+1);
            this.getXLbean+=cur.value*(res.length+1);
            if(this.getXLbean >= this.todayCanGetXileBean){
                this.getXLbean = this.todayCanGetXileBean;
            }else{
                setTimeout(()=>{
                    this.createScoreNode(cur.node, cur.value*(res.length+1))
                }, 300)
                
            }
            res.map(item=>{
                item.value = 0;
                item.ani.call(()=>{
                    item.ani = null;
                    item.node.children[0].destroy();
                }).start()
            })
            
            setTimeout(()=>{
                cur.value++;
                let sprite = this.polygonSpriteFrame.filter(item=>{
                    return item._name == cur.value
                });
                if(sprite[0]){
                    sprite = sprite[0]
                    cur.node.children[0].getComponent(cc.Sprite).spriteFrame = sprite;            
                    this.removePolygon(x, y)      
                }else{
                    this.clearRound(cur, x, y);
                }
                this.updateMax();
            }, 300)        
        }
        this.arenaData.forEach(item=>{
            item.map(item2=>{
                item2.find = false;
            })
        })
        clearTimeout(this.saveDataTimer);
        this.saveDataTimer = setTimeout(()=>{
            this.saveCurStatus();
        }, 3000)

        this.setNextPoly()
    },
    setNextPoly(){
        let arr = [];
        this.arenaData.forEach(item=>{
            arr = arr.concat(item.filter(item2=>item2.value == 0));
        })
        if(arr.length <= 15 && arr.length > 0){
            let resJson = {
                'b': false,
                'c': false,
                'd': false
            }
            for(let y=0; y<this.arenaData.length; y++){
                for(let x=0; x<this.arenaData[y].length; x++){
                    if(this.arenaData[y][x].value == 0){

                        let a = this.find2(y, x-1);
                        let b = this.find2(y, x+1);
                        if(a || b){
                            resJson.b = true;
                        }
                        let c = this.find2(y-1, x);
                        let d = null;
                        if(y-1>=0 && this.arenaData[y-1].length < this.arenaData[y].length){
                            d = this.find2(y-1, x-1);
                            if(d){
                                resJson.d = true;
                            }
                            if(c){
                                resJson.c = true;
                            }
                        }else{
                            d = this.find2(y-1, x+1);  
                            if(d){
                                resJson.c = true;
                            }
                            if(c){
                                resJson.d = true;
                            }                    
                        }        
                        let e = this.find2(y+1, x);
                        let f = null;
                        if(y+1<this.maxLen && this.arenaData[y+1].length < this.arenaData[y].length){
                            f = this.find2(y+1, x-1);
                            if(e){
                                resJson.d = true;
                            }
                            if(f){
                                resJson.c = true;
                            }
                        }else{
                            f = this.find2(y+1, x+1);
                            if(e){
                                resJson.c = true;
                            }
                            if(f){
                                resJson.d = true;
                            }                    
                        }
                    }
                }
            }
            let arr2 = Object.keys(resJson).filter(item=>resJson[item]);
            if(arr2.length != 0){
                arr2.sort(()=>Math.random()-0.5);
                this.nextPoly = arr2[0]
            }else{
                this.nextPoly = 'a';
            }
        }else if(arr.length == 0){
            //console.log('没有空位了！')
            clearTimeout(this.saveDataTimer)
            clearTimeout(this.gameOverTimer);
            this.gameOverTimer = setTimeout(()=>{
                this.callGameOver();
            },100)
        }else{
            let rnd = Math.random();
            let arr = ['b', 'c', 'd']
            arr.sort(()=>Math.random()-0.5)
            if(rnd<0.2){    
                this.nextPoly = 'a';
            }else{
                this.nextPoly = arr[0]
            }
        }
    },
    resetAll(){
        for(let y=0; y<this.arenaData.length; y++){
            for(let x=0; x<this.arenaData[y].length; x++){
                this.arenaData[y][x].value = 0;
                this.arenaData[y][x].node.children[0].destroy();
            }
        }
        this.max = 2;
    },
    clearRound(cur,y,x){
        let a = this.find(y, x-1);
        let b = this.find(y, x+1);
        let c = this.find(y-1, x);
        let d = null;
        if(y-1>=0 && this.arenaData[y-1].length < this.arenaData[y].length){
            d = this.find(y-1, x-1);
        }else{
            d = this.find(y-1, x+1);       
        }        
        let e = this.find(y+1, x);
        let f = null;       
        if(y+1<this.maxLen && this.arenaData[y+1].length < this.arenaData[y].length){
            f = this.find(y+1, x-1);    
        }else{
            f = this.find(y+1, x+1);
        }
        let arr = [cur, a, b, c, d, e, f];
        arr.map(item=>{
            if(item && item.value != 0){
                item.ani = null;
                item.node.children[0].destroy();
                this.score+=item.value;
                item.value = 0;
            }
        })
    },
    updateMax(){
        let max = 2;
        for(let i=0; i<this.arenaData.length; i++){
            for(let j=0; j<this.arenaData[i].length; j++){
                let cur = this.arenaData[i][j];
                if(cur.value && cur.value > max){
                    max = cur.value
                }
            }
        };
        //console.log('max', max)
        this.max = max;
    },
    getAni(a, b){
        let disPos = a.node.children[0].convertToWorldSpaceAR(cc.v2(0,0)).sub(b.node.children[0].convertToWorldSpaceAR(cc.v2(0,0)));
        let tt = cc.tween(b.node.children[0]).by(0.3, {position: disPos, opacity: -255})
        return tt;
    },
    //查找周围的六边形
    findPolygon(res, cur, y, x){
        let findA = false;
        let findB = false;
        let findC = false;
        let findD = false;
        let findE = false;
        let findF = false;

        let a = this.find(y, x-1);
        if(a && !a.find && a.value == cur.value){
            a.ani = this.getAni(cur, a);
            res.push(a)
            a.find = true;
            findA = true;
            a.target = cur;
        }
        let b = this.find(y, x+1);
        if(b && !b.find && b.value == cur.value){
            b.ani = this.getAni(cur, b);
            res.push(b)
            b.find = true;
            findB = true;
            b.target = cur;
        }
        let c = this.find(y-1, x);
        let d = null;
        let dPos
        if(y-1>=0 && this.arenaData[y-1].length < this.arenaData[y].length){
            d = this.find(y-1, x-1);
            if(d && !d.find && d.value == cur.value && cur.value){
                d.ani = this.getAni(cur, d);
                res.push(d)
                d.find = true;
                findD = true;
                dPos = [y-1, x-1];
                d.target = cur;
            }            
        }else{
            d = this.find(y-1, x+1);
            if(d && !d.find && d.value == cur.value && cur.value){
                d.ani = this.getAni(cur, d)
                res.push(d)
                d.find = true;
                findD = true;
                dPos = [y-1, x+1];
                d.target = cur;
            }               
        }
        if(c && !c.find && c.value == cur.value && cur.value){
            c.ani = this.getAni(cur, c);
            res.push(c)
            c.find = true;
            findC = true;
            c.target = cur;
        }

        let e = this.find(y+1, x);
        let f = null;         
        let fPos
        if(y+1<this.maxLen && this.arenaData[y+1].length < this.arenaData[y].length){
            f = this.find(y+1, x-1);
            if(f && !f.find && f.value == cur.value && cur.value){
                f.ani = this.getAni(cur, f);
                res.push(f)
                f.find = true;
                findF = true;
                fPos = [y+1, x-1]
                f.target = cur;
            }             
        }else{
            f = this.find(y+1, x+1);
            if(f && !f.find && f.value == cur.value && cur.value){
                f.ani = this.getAni(cur, f);
                res.push(f)
                f.find = true;
                findF = true;
                fPos = [y+1, x+1]
                f.target = cur;
            }
        }
        if(e && !e.find && e.value == cur.value && cur.value){
            e.ani = this.getAni(cur, e);
            res.push(e)
            e.find = true;
            findE = true;
            e.target = cur;
        }    
        findA&&this.findPolygon(res,a, y, x-1);
        findB&&this.findPolygon(res,b, y, x+1)
        findC&&this.findPolygon(res,c, y-1, x)
        findD&&this.findPolygon(res,d, dPos[0], dPos[1])
        findE&&this.findPolygon(res,e, y+1, x)
        findF&&this.findPolygon(res,f, fPos[0], fPos[1])
    },
    find(y, x){
        if(this.arenaData[y] && this.arenaData[y][x]){
            return this.arenaData[y][x]
        }else{
            return null;
        }
    },
    find2(y, x){
        if(this.arenaData[y] && this.arenaData[y][x] && this.arenaData[y][x].value == 0){
            return this.arenaData[y][x]
        }else{
            return null;
        }
    },    
    printArenaData(){
        let arr = [];
        for(let i=0; i<this.arenaData.length; i++){
            let arr2 = [];
            for(let j=0; j<this.arenaData[i].length; j++){
                arr2.push(this.arenaData[i][j].value)
            }
            arr.push(arr2)
        }
        console.table(arr);
    },    
    //创建棋盘
    createArena(){
        let h = 0;
        let w = (this.maxLen-1)*(this.polygonW+this.polygonStepX) - this.polygonStepX;
        for(let i=0; i<this.arenaData.length; i++){
            let node = new cc.Node();
            node.x = (this.maxLen-this.arenaData[i].length)*((this.polygonW+this.polygonStepX)/2)
            node.y = i*(this.polygonH - this.polygonH*Math.sin(30*Math.PI/180)/2 + this.polygonStepY)
            h = node.y;
            for(let j=0; j<this.arenaData[i].length; j++){
                let item = cc.instantiate(this.polygonPrefab);
                item.pos = [i,j];
                item.setPosition(cc.v2(j*(this.polygonW+this.polygonStepX), 0))
                node.addChild(item);
                let val = this.arenaData[i][j];
                this.arenaData[i][j] = {
                    value: val,
                    node: item
                }
                if(val != 0){
                    let childNode = this.createOne(val);
                    item.addChild(childNode)
                }
            }
            this.arenaNode.addChild(node);
        }
        this.arenaNode.x = -w/2;
        this.arenaNode.y = (-h/2) - 30
    },    
    createOne(n){
        let sprite = this.polygonSpriteFrame.filter(item=>{
            return item._name == n
        })[0];
        let node = cc.instantiate(this.polygon2Prefab);
        node.getComponent(cc.Sprite).spriteFrame = sprite;
        node.value = n;
        node.setPosition(cc.v2(0,0))
        return node
    },  
    //获取数量最多的数字  
    getManyNum(){
        let map = {};
        let resNum = 0;
        let max = 0;
        for(let i=0; i<this.arenaData.length; i++){
            for(let j=0; j<this.arenaData[i].length; j++){
                let cur = this.arenaData[i][j];
                if(cur.value != 0){
                    if(map[cur.value]){
                        map[cur.value]++;
                        if(map[cur.value] > max){
                            max = map[cur.value];
                            resNum = cur.value
                        }
                    }else{
                        map[cur.value] = 1;
                    }
                }
            }
        }
        return resNum || 1
    },
    getRandNum(){
        let sum = 0;
        let cur = this.max;
        while(cur>0){
            sum+=cur;
            cur--;
        }
        let aRate = [];
        for(let i=1; i<=this.max; i++){
            aRate.push( (this.max+1-i)/sum )
        }
        let sumRate = 0;
        let radNum = Math.random();
        let resNum = 0;
        //console.log(aRate, radNum)
        for(let i=0; i<aRate.length; i++){
            if(sumRate < radNum && radNum < (sumRate+aRate[i])){
                resNum = i+1;
                break;
            }else{
                sumRate+=aRate[i];
            }
        }
        return resNum
    },
    //创建棋子
    createPolygon(style){
        let node1 = null;
        let node2 = null;
        if(style == 'a'){
            node1 = this.createOne(this.getRandNum())
            this.dragPolygonNode.addChild(node1);
        }else{
            node1 = this.createOne(this.getRandNum())
            node2 = this.createOne(this.getRandNum())
            this.dragPolygonNode.addChild(node1);
            this.dragPolygonNode.addChild(node2);
        }
        let posX = (this.polygonW+this.polygonStepX)/2;
        let posY = this.polygonH - this.polygonH*Math.sin(30*Math.PI/180)/2 + this.polygonStepY;
        switch(style){
            case 'a':
                this.dragPolygonNode.setPosition(cc.v2(0,0))
                break;
            case 'b':
                node2.setPosition(cc.v2(this.polygonW+this.polygonStepX, 0))
                this.dragPolygonNode.setPosition(cc.v2(-(this.polygonW+this.polygonStepX)/2, 0))
                break;
            case 'c':
                node2.setPosition(cc.v2(posX, -posY))
                this.dragPolygonNode.setPosition(cc.v2(-posX/2, posY/2))
                break;    
            case 'd':
                node2.setPosition(cc.v2(posX, posY))
                this.dragPolygonNode.setPosition(cc.v2(-posX/2, -posY/2))
                break;                                                  
        }
    },    
    update (dt) {
        this._update(dt);

        this.cirNode.angle+=1;
    },
});
